面试官:Go GMP 模型为什么 P 组件如此重要 ?

您所在的位置:网站首页 golang gmp模型讲解 面试官:Go GMP 模型为什么 P 组件如此重要 ?

面试官:Go GMP 模型为什么 P 组件如此重要 ?

2024-07-11 04:41| 来源: 网络整理| 查看: 265

大家好,我是木川

Go GMP模型 是 Go语言并发性能的关键组成部分,它允许轻松创建大量的 Goroutines,设计思想包括并行性、线程复用以及抢占调度。

Go 1.1 版本前采用的是 GM 模型,存在一些问题,后面增加了 P 组件,实现了 GMP 模型。

一、什么是 GM 模型

Go 在 1.1 版本之前是 GM 模型,GM 模型包含 2 个重要结构,分别是 G、M,没有 P 组件。

f10db98836ba2e7119b8ebabca625a67.png

G(Goroutines):用户线程,通过 go 关键字创建,初始栈大小为 2-4K。

M(Machine):操作系统线程,进入一个调度循环,从全局队列中获取 G,切换到 G 的执行栈上并执行 G 的函数。

二、GM 模型存在的问题 全局队列的锁竞争

当 M 执行 G,必须访问全局队列,因为 M 有多个,当多线程访问同一资源需要加锁保证线程安全,导致激烈的锁竞争。

M 转移 G 增加额外开销

当 M1 在执行 G1 的时候, G1 包含创建新协程 G2,M1 创建了 G2,为了继续执行 G1,需要把 G2 保存到全局队列中,无法保证 G2 是被 M1 处理,造成了很差的局部性。

因为 M1 原本就保存了 G2 的信息,所以 G2 最好是在 M1 上执行,这样的话也不需要转移 G 到全局队列和线程上下文切换。

三、什么是 GMP 模型

为了解决 GM 模型上面存在的问题,在 GM 模型的基础上,新增了一个 P(Processor)组件,让 P 去管理这个 G 对象,M 想要运行 G,必须绑定 P,才能运行 P 所管理的 G。

GMP 模型包含 3 个重要结构,分别是 G、M、P。

e0b013174e19085712816aee3e8c24d8.png

G(Goroutines):用户线程,通过 go 关键字创建,初始栈大小为 2-4K。

M(Machine):操作系统线程,M 在绑定有效的 P 后,进入一个调度循环,从 P 中获取 G,切换到 G 的执行栈上并执行 G 的函数。

P(Processor):调度上下文,维护了一组 Goroutine 队列。

四、加了 P 之后解决的问题

每个 P 有自己的本地队列,大幅度减轻了对全局队列的直接依赖,减少了锁竞争。而 GM 模型的性能开销大头就是锁竞争。

局部性较好,当 M1 在执行 G1 的时候, G1 包含创建新协程 G2,M1 创建了 G2,直接将 G2 保存到当前绑定的 P 上,G2 大概率也是被 M1 执行,不需要将 G2 转移到全局 G 队列增加额外开销。

五、为什么 P 的逻辑不加到 M 上

M 的数量都会多于 P(M 的数量默认上限是 10000,P 的默认数量是 CPU 核数), M 如果执行 G 发生系统阻塞调用,阻塞了 M,又不够用的情况下,M 会不断增加,如果本地 G 队列挂载在 M 上,那就意味着本地队列也会随之增加。如果 P 的逻辑加到 M上,导致本地队列的管理会变得复杂,且 work stealing 性能会大幅度下降。

如果 P 的逻辑直接加到 M 上,一旦 M 发生系统调用阻塞,会导致 P 上剩余的 G 也无法执行,G 的并发执行效率下降

六、总结

P 是 Go GMP 模型的关键组件,P 的存在防止一个阻塞的 Goroutine 阻塞整个 M,提高了应用程序的响应性,它在实现高效的并发性能、资源管理等方面发挥了至关重要的作用。

最后给自己的原创 Go 面试小册打个广告,如果你从事 Go 相关开发,欢迎扫码购买,目前 10 元买断,加下面的微信发送支付截图额外赠送一份自己录制的 Go 面试题讲解视频

cef207924728dd2d1b51e773bccf5710.jpeg

147042a79a90af7a39d961e42b10b64a.png

如果对你有帮助,帮我点一下在看或转发,欢迎关注我的公众号



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3